home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1990: Night of the Living Disc / Night of the Living Disc.hdv / Dev.CD.5 / Tools / Technical.Notes / IIGS / TN.IIGS.071 < prev    next >
Encoding:
Text File  |  1990-08-21  |  11.9 KB  |  282 lines  |  [04] ASCII Text (0x0000)

  1. Apple II
  2. Technical Notes
  3. _____________________________________________________________________________
  4.                                                   Developer Technical Support
  5.  
  6. Apple IIgs
  7. #71:    DA Tips and Techniques
  8.  
  9. Revised by:    Dave "Mr. Tangent" Lyons                        September 1990
  10. Written by:    Dave Lyons                                       November 1989
  11.  
  12. This Technical Note presents tips and techniques for writing Desk Accessories.
  13. Changes since July 1990:  Modified discussion of NDAs and Command keystrokes, 
  14. made two additions and one correction to the recommended steps for an NDA to 
  15. use its resource fork, and added discussion of NDAs presenting modal dialog 
  16. boxes.  In addition, added sections on avoiding hard-coded pathnames and 
  17. making unneeded GetNewID calls.
  18. _____________________________________________________________________________
  19.  
  20.  
  21. Classic Desk Accessory Tips and Techniques
  22.  
  23. Reading the Keyboard
  24.  
  25. For a CDA that runs only under GS/OS, the Console Driver is the best choice 
  26. for reading from the keyboard.  Other CDAs have two cases to deal with:  the 
  27. Event Manager may or may not be started.  The Text Tools can read the keyboard 
  28. in either case, but you should avoid using the Text Tools whenever possible 
  29. (see Apple IIgs Technical Note #69, The Ins and Outs of Slot Arbitration).
  30.  
  31. You can call EMStatus to determine whether the Event Manager is started.  When 
  32. it is, you can read keypresses by calling GetNextEvent.  When the Event 
  33. Manager is not started, you can read keys directly from the keyboard hardware 
  34. by waiting for bit 7 of location $E0C000 to turn on.  When it does, the lower 
  35. seven bits represent the key pressed.  Once you've detected a keypress, you 
  36. need to write to location $E0C010 to remove the keypress from the buffer.
  37.  
  38. Alternately, you can use IntSource (in the Miscellaneous Tools) to temporarily 
  39. disable keyboard interrupts and then read the keyboard hardware directly.  Be 
  40. sure to reactivate keyboard interrupts if, and only if, they were previously 
  41. enabled.
  42.  
  43. Just One Page of Stack Space
  44.  
  45. CDAs normally have only a single page of stack space available to them (256 
  46. bytes at $00/01xx).  Your CDA may or may not be able to allocate additional 
  47. stack space from bank 0 during execution.  The following code (written for the 
  48. MPW IIgs cross-assembler) shows a safe way to try to allocate more stack space 
  49. and to switch between stacks when the space is available.
  50.  
  51. If ProDOS 8 is active, your CDA cannot allocate additional space (and there is 
  52. no completely safe way to "borrow" bank 0 space from the ProDOS 8 
  53. application).
  54.  
  55.  
  56. HowMuchStack   gequ    $1000          ;try for 4K of stack space
  57.  
  58. start          phd
  59.                phb
  60.                phk
  61.                plb
  62.                pha                    ;Space for result
  63.                pha
  64.                PushLong #HowMuchStack
  65.                pha
  66.                _MMStartUp
  67.                pla
  68.                ora    #$0f00          ;OR in an arbitrary auxiliary ID
  69.                pha
  70.                PushWord #$C001        ;fixed, locked, use specified bank
  71.                PushLong #0            ;(specify bank 0)
  72.                _NewHandle
  73.                tsc
  74.                sta    theOldStack
  75.                bcs    NoStackSpace    ;still set from _NewHandle
  76.                tcd
  77.                lda    [1]
  78.                tcd
  79. ;               clc                    ;carry is already clear
  80.                adc    #HowMuchStack-1
  81. NoStackSpace   pha
  82.                ldx    #$fe
  83. keepStack      lda    >$000100,x
  84.                sta    stackImage,x
  85.                dex
  86.                dex
  87.                bpl    keepStack
  88.                pla
  89.                tcs
  90.                jsl    RealCDAentry   ;carry is clear if large stack available
  91.                php
  92.                php
  93.                pla
  94.                sta    pRegister
  95.                sei
  96.                ldx    #$fe
  97. restoreStack   lda    stackImage,x
  98.                sta    >$000100,x
  99.                dex
  100.                dex
  101.                bpl    restoreStack
  102.                lda    theOldStack
  103.                tcs
  104.                lda    pRegister
  105.                pha
  106.                plp
  107.                plp
  108.                lda    1,s
  109.                ora    3,s
  110.                beq    noDispose
  111.                _DisposeHandle
  112.                bra    Exit
  113. noDispose      pla
  114.                pla
  115. Exit           plb
  116.                pld
  117.                rtl
  118. pRegister     ds 2
  119. theOldStack   ds 2
  120. stackImage    ds.b 256
  121.  
  122. When this routine calls RealCDAentry, the carry flag is set if no extra stack 
  123. space is available.  If the carry is clear, the additional stack space was 
  124. available and the direct-page register points to the bottom of that space.
  125.  
  126. RealCDAentry   bcs    smallStack  ;if c set, only 1 page of stack is available
  127.                ...                ; put something interesting here
  128.                rtl
  129.  
  130. smallStack     _SysBeep
  131.                rtl
  132.  
  133. Note that interrupts are disabled while the page-one stack is being restored; 
  134. they are reenabled (if they were originally enabled) only after the stack 
  135. pointer is safely back in page one.
  136.  
  137.  
  138. New Desk Accessory Tips and Techniques
  139.  
  140. NDAs Continue to Get Command- Keystrokes
  141.  
  142. Previous versions of this Note said that NDAs are not guaranteed to receive 
  143. key-down events with the Command key down, because System Software might be 
  144. revised to pass such keys directly to the current application instead.
  145.  
  146. In light of the reaction of several interested parties, that warning is being 
  147. withdrawn.  When an NDA is in front, it has first crack at key-down events, 
  148. even when the Command key is down.
  149.  
  150. There is currently no way for an NDA to accept some keystrokes and pass others 
  151. along to applications, but if your NDA does not want any keystroke events, 
  152. turn off the corresponding eventMask bits in the NDA header (this allows the 
  153. application to receive keystrokes while your NDA window is in front).
  154.  
  155. You may want to support the standard Close key equivalent, Command-W.  When 
  156. your NDA's action routine receives an Command-W (or Command-w) keyDown or 
  157. autoKey event, you can call CloseNDAByWinPtr with your own window pointer.  
  158. This causes a call to your NDA's Close routine within the call to your Action 
  159. routine--if your code has no problem with this, neither does the Desk Manager.
  160.  
  161. Calling InstallNDA From Within an NDA
  162.  
  163. It is possible to write an NDA that installs other NDAs.  However, with System 
  164. Software 5.0 and later, InstallNDA returns an error when called from an NDA.  
  165. When your NDA has control because the Desk Manager called one of your NDA's 
  166. entry points, the Desk Manager's data structures are already in use, so 
  167. InstallNDA is unable to modify them.
  168.  
  169. The solution is to use SchAddTask in the Scheduler to postpone the InstallNDA 
  170. call until the system is not busy.  Remember that the Bank and Direct Page 
  171. registers are not defined when your scheduled task is executed.
  172.  
  173. Processing mouseUp Events
  174.  
  175. When an NDA's action routine receives a mouseUp event, it is not always safe 
  176. for the NDA to draw in its window.
  177.  
  178. For example, when the user drags an NDA window, the NDA receives the mouseUp 
  179. before the window is actually moved, and before DragWindow erases the outline 
  180. of the new window position, which may overlap the window's content.  In 
  181. addition, when the user chooses a menu item, the front NDA receives the 
  182. mouseUp before the menu's image is removed, and the image may overlap the 
  183. NDA's window.  In either case, drawing in the window makes a mess.
  184.  
  185. The solution is to avoid drawing in direct response to a mouseUp.  Instead, 
  186. invalidate part of the window to force an update event to happen later.
  187.  
  188. NDAs Can Have Resource Forks
  189.  
  190. Following is the recommended way for a New Desk Accessory to use its file's 
  191. resource fork.
  192.  
  193. In the NDA's Open routine, do the following:
  194.  
  195.    1.  Call GetCurResourceApp and keep the result.
  196.    2.  If the NDA does not already know its Memory Manager user ID, call 
  197.        MMStartUp to get it.
  198.    3.  Call ResourceStartUp using the NDA's user ID.
  199.    4.  Call the Loader function LGetPathname2 with the NDA's user ID (and a 
  200.        fileNumber of $0001) to get a pointer to the NDA's pathname.  (The 
  201.        result is a pointer to a class-one GS/OS string.)
  202.    5.  Use GetLevel to get the current file level, then use SetLevel to set 
  203.        it to zero.  This helps protect your resource fork from being closed 
  204.        accidentally.
  205.    6.  Use GetSysPrefs to get the current OS preferences, then use 
  206.        SetSysPrefs to ensure that the user is prompted, if necessary, to 
  207.        insert the disk containing your resource fork.  (To compute the new 
  208.        preferences word, take the current one, AND it with $1FFF, and ORA it 
  209.        with $8000.  This tells GS/OS to deal with volume-not-found conditions 
  210.        by putting up a please-insert-disk dialog with an OK button and a 
  211.        Cancel button.)
  212.    7.  Call OpenResourceFile using the result from LGetPathname2.  Save the 
  213.        returned fileID--you need it when closing the file.  (Be prepared to 
  214.        deal with an error, such as $0045, Volume Not Found.)
  215.    8.  Use SetSysPrefs to restore the OS preferences saved in step six.
  216.    9.  Use SetLevel to restore the file level to its old value (saved in step 
  217.        five).
  218.   10.  Call SetCurResourceApp with the old value saved in step one.
  219.  
  220. In the NDA's action routine, no special calls are necessary--the Desk Manager 
  221. calls SetCurResourceApp automatically before calling your action routine, so 
  222. your NDA's own resource search path is already in effect.
  223.  
  224. Run queue routines and NDA installs with AddToRunQ are treated the same way--
  225. the NDA's resource search path is automatically in effect when the run queue 
  226. routine is called.
  227.  
  228. In the NDA's Close routine, do the following:
  229.  
  230.    1.  Call CloseResourceFile with the fileID that was returned when you 
  231.        opened it.
  232.    2.  Call ResourceShutDown with no parameters (the last version of this 
  233.        Note incorrectly said to pass the NDA's User ID--oops).
  234.  
  235. NDAs Must Be Careful Handling Modal Windows
  236.  
  237. If your NDA uses its resource fork and calls TaskMaster with a restricted 
  238. wmTaskMask to produce a modal window, you must be careful not to allow 
  239. TaskMaster to update the contents of any application windows that happen to 
  240. need updating.
  241.  
  242. The problem is that an application window's wContDraw routine can reasonably 
  243. assume that the current Resource Manager search path is the application's, but 
  244. TaskMaster does not take any special steps to set it.  When the content-draw 
  245. routine draws controls which were created from resources which are not 
  246. presently in the resource search path, the system may crash.
  247.  
  248. If your NDA does not start up the Resource Manager, the Desk Manager is unable 
  249. to SetCurResourceApp to your NDA, so the application's search path is still in 
  250. effect--no problem.  But if your NDA does start the Resource Manager, you have 
  251. to be careful not to cause application routines to be called.
  252.  
  253. Avoid Hard-Coding Your Pathname
  254.  
  255. If your NDA needs to know its own pathname or the pathname of the directory 
  256. it's in, call LGetPathname or LGetPathname2 using your User ID.  This is a 
  257. better method than hard-coding "*:System:Desk.Accs:MyDAName" because the user 
  258. may change your DA's file name or use a utility to install it from some non-
  259. standard directory.
  260.  
  261. Avoid Extra GetNewID calls
  262.  
  263. Normally there is no reason for a Desk Accessory to call GetNewID.  When you 
  264. can, just call MMStartUp to find your own User ID, and use that.  You can 
  265. freely use all the auxiliary IDs derived from your main ID (MMStartUp+$0100, 
  266. MMStartUp+$0200, ..., MMStartUp+$0F00).
  267.  
  268. By not calling GetNewID, you conserve the limited supply of IDs (255 of in the 
  269. $50xx range for Desk Accessories), and you make life easier for people trying 
  270. to debug their systems, since all your allocated memory can be readily 
  271. identified.
  272.  
  273.  
  274. Further Reference
  275. _____________________________________________________________________________
  276.   o  Apple IIgs Toolbox Reference, Volumes 1-3
  277.   o  GS/OS Reference
  278.   o  Apple IIgs Hardware Reference
  279.   o  Apple IIgs Technical Note #53, Desk Accessories and Tools
  280.   o  Apple IIgs Technical Note #69, The Ins and Outs of Slot Arbitration
  281.  
  282.